#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
福特配置器最终分析工具
整合20秒延迟和改进的Cookie处理机制
专门用于深度分析福特NGc2配置器的完整流程
"""

import json
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, ElementClickInterceptedException, NoSuchElementException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service


class FinalConfiguratorAnalyzer:
    """最终配置器分析工具"""
    
    def __init__(self):
        self.driver = None
        self.wait = None
        self.analysis_results = {}
        self.html_snapshots = {}
        self.detected_models = []
        self.setup_driver()
    
    def setup_driver(self):
        """初始化Chrome WebDriver"""
        try:
            print("正在初始化Chrome WebDriver...")
            
            options = Options()
            options.add_argument('--no-sandbox')
            options.add_argument('--disable-dev-shm-usage')
            options.add_argument('--disable-gpu')
            options.add_argument('--window-size=1920,1080')
            
            # 清除所有cookies和缓存
            options.add_argument('--disable-extensions')
            options.add_argument('--disable-plugins')
            options.add_argument('--disable-images')  # 加快加载
            options.add_argument('--disable-web-security')
            
            # 设置User-Agent
            options.add_argument('--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
            
            # 反检测设置
            options.add_argument('--disable-blink-features=AutomationControlled')
            options.add_experimental_option("excludeSwitches", ["enable-automation"])
            options.add_experimental_option('useAutomationExtension', False)
            
            try:
                from webdriver_manager.chrome import ChromeDriverManager
                service = Service(ChromeDriverManager().install())
                self.driver = webdriver.Chrome(service=service, options=options)
            except Exception:
                self.driver = webdriver.Chrome(options=options)
            
            self.wait = WebDriverWait(self.driver, 30)
            
            # 清除所有cookies
            self.driver.delete_all_cookies()
            
            # 设置反检测脚本
            self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
            
            print("WebDriver初始化成功")
            
        except Exception as e:
            print(f"WebDriver初始化失败: {e}")
            raise
    
    def enhanced_cookie_handler(self):
        """增强的Cookie处理机制"""
        print("🍪 执行增强的Cookie处理...")
        
        try:
            # 方法1: 检测并处理特定的福特Cookie类
            ford_cookie_success = self.handle_ford_specific_cookies()
            
            # 方法2: 通用Cookie处理
            generic_cookie_success = self.handle_generic_cookies()
            
            # 方法3: 强制清理所有可能的阻塞元素
            force_cleanup_success = self.force_cleanup_blocking_elements()
            
            # 只要任何一种方法成功就返回成功
            overall_success = ford_cookie_success or generic_cookie_success or force_cleanup_success
            
            if overall_success:
                print("✅ Cookie处理完成")
                # 最终验证
                self.verify_page_interactivity()
            else:
                print("⚠️  Cookie处理未完全成功，但继续执行")
            
            return True
            
        except Exception as e:
            print(f"❌ Cookie处理过程出错: {e}")
            return False
    
    def handle_ford_specific_cookies(self):
        """处理福特特定的Cookie弹窗"""
        print("  🎯 处理福特特定Cookie...")
        
        # 基于深度分析发现的福特网站Cookie类
        ford_selectors = [
            '.styles__CookieDisclaimerWrapper-sc-dx4a8y-0.bByYil',
            '.styles__CookieDisclaimerContent-sc-dx4a8y-3.hUJXDq',
            '[class*="styles__CookieDisclaimer"]',
            'div[role="dialog"][class*="Cookie"]'
        ]
        
        found_elements = []
        for selector in ford_selectors:
            try:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                for element in elements:
                    if element.is_displayed():
                        found_elements.append(element)
                        print(f"    ✓ 发现福特Cookie元素: {selector}")
            except Exception:
                continue
        
        if found_elements:
            # 尝试在这些容器内找同意按钮
            for container in found_elements:
                try:
                    buttons = container.find_elements(By.TAG_NAME, 'button')
                    for button in buttons:
                        if self.is_consent_button(button):
                            self.click_element_safely(button)
                            print(f"    ✅ 点击了福特Cookie同意按钮")
                            time.sleep(2)
                            return True
                except Exception:
                    continue
            
            # 如果找不到按钮，直接移除容器
            for element in found_elements:
                try:
                    self.driver.execute_script("arguments[0].remove();", element)
                    print(f"    🗑️  移除了福特Cookie容器")
                except Exception:
                    continue
            return True
        
        return False
    
    def handle_generic_cookies(self):
        """处理通用Cookie弹窗"""
        print("  🌐 处理通用Cookie...")
        
        generic_selectors = [
            'button[data-testid*="accept"]',
            'button[id*="accept"]',
            'button[class*="accept"]',
            'button[aria-label*="accept" i]',
            '[role="dialog"] button',
            '.cookie-accept',
            '#cookie-accept',
            'button'
        ]
        
        for selector in generic_selectors:
            try:
                buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                for button in buttons:
                    if self.is_consent_button(button):
                        self.click_element_safely(button)
                        print(f"    ✅ 点击了通用Cookie同意按钮")
                        time.sleep(2)
                        return True
            except Exception:
                continue
        
        return False
    
    def force_cleanup_blocking_elements(self):
        """强制清理所有阻塞元素"""
        print("  🧹 强制清理阻塞元素...")
        
        try:
            # JavaScript清理脚本
            cleanup_script = """
            // 移除所有可能的Cookie相关元素
            var selectors = [
                '[class*="cookie"]',
                '[class*="Cookie"]',
                '[class*="consent"]',
                '[class*="disclaimer"]',
                '[role="dialog"]',
                '[class*="modal"]',
                '[class*="overlay"]',
                '[class*="backdrop"]'
            ];
            
            var removedCount = 0;
            selectors.forEach(function(selector) {
                try {
                    var elements = document.querySelectorAll(selector);
                    elements.forEach(function(el) {
                        if (el.offsetParent !== null) { // 检查是否可见
                            var rect = el.getBoundingClientRect();
                            if (rect.width > 100 && rect.height > 50) { // 过滤掉太小的元素
                                el.style.display = 'none';
                                el.remove();
                                removedCount++;
                            }
                        }
                    });
                } catch(e) {}
            });
            
            // 重置页面样式
            document.body.style.overflow = 'auto';
            document.documentElement.style.overflow = 'auto';
            
            // 移除可能阻止交互的样式
            var allElements = document.querySelectorAll('*');
            for (var i = 0; i < allElements.length; i++) {
                var el = allElements[i];
                if (el.style.pointerEvents === 'none') {
                    el.style.pointerEvents = 'auto';
                }
            }
            
            return removedCount;
            """
            
            removed_count = self.driver.execute_script(cleanup_script)
            if removed_count > 0:
                print(f"    🗑️  强制移除了 {removed_count} 个可能的阻塞元素")
                time.sleep(1)
                return True
            
        except Exception as e:
            print(f"    ❌ 强制清理失败: {e}")
        
        return False
    
    def is_consent_button(self, button):
        """判断是否是同意按钮"""
        try:
            if not button.is_displayed() or not button.is_enabled():
                return False
            
            button_text = button.text.strip().lower()
            button_class = (button.get_attribute('class') or '').lower()
            button_aria_label = (button.get_attribute('aria-label') or '').lower()
            
            # 同意关键词
            consent_keywords = [
                'accept', 'agree', 'allow', 'ok', 'continue', 
                'consent', 'yes', 'i agree', 'accept all'
            ]
            
            # 拒绝关键词（要避免）
            reject_keywords = [
                'reject', 'decline', 'refuse', 'deny', 'no',
                'manage', 'settings', 'preferences', 'customize'
            ]
            
            has_consent = any(keyword in button_text or keyword in button_class or keyword in button_aria_label 
                            for keyword in consent_keywords)
            has_reject = any(keyword in button_text or keyword in button_class or keyword in button_aria_label 
                           for keyword in reject_keywords)
            
            return has_consent and not has_reject
            
        except Exception:
            return False
    
    def click_element_safely(self, element):
        """安全地点击元素"""
        try:
            # 滚动到元素
            self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)
            time.sleep(0.5)
            
            # 尝试普通点击
            try:
                element.click()
            except ElementClickInterceptedException:
                # 使用JavaScript点击
                self.driver.execute_script("arguments[0].click();", element)
                
        except Exception as e:
            # 最后尝试：强制JavaScript点击
            try:
                self.driver.execute_script("arguments[0].click();", element)
            except Exception:
                raise e
    
    def verify_page_interactivity(self):
        """验证页面交互性"""
        print("  🔍 验证页面交互性...")
        
        try:
            # 尝试找到车型元素并检查是否可点击
            model_elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]')
            
            clickable_models = 0
            for model in model_elements[:3]:  # 只检查前3个
                data_cy = model.get_attribute('data-cy')
                if data_cy and data_cy not in ['header-selling-price', 'sticky-bar']:
                    try:
                        # 检查元素是否在视口内且可点击
                        rect = self.driver.execute_script("""
                            var rect = arguments[0].getBoundingClientRect();
                            return {
                                x: rect.x,
                                y: rect.y,
                                width: rect.width,
                                height: rect.height,
                                visible: rect.width > 0 && rect.height > 0
                            };
                        """, model)
                        
                        if rect['visible']:
                            clickable_models += 1
                            
                    except Exception:
                        continue
            
            print(f"    ✓ 发现 {clickable_models} 个可交互的车型元素")
            return clickable_models > 0
            
        except Exception as e:
            print(f"    ❌ 验证交互性失败: {e}")
            return False
    
    def analyze_complete_flow(self, url):
        """分析完整的配置流程"""
        try:
            print(f"🚀 开始完整流程分析: {url}")
            print("=" * 80)
            
            # 步骤1: 访问页面并等待完全加载
            print("\\n📱 步骤1: 页面加载")
            self.driver.get(url)
            
            print("⏱️  等待页面完全加载（20秒延迟）...")
            for i in range(20):
                time.sleep(1)
                if i % 5 == 4:
                    print(f"    加载进度: {i+1}/20秒")
            
            print("✅ 页面加载完成")
            
            # 步骤2: 捕获初始状态
            print("\\n📸 步骤2: 捕获初始状态")
            self.capture_detailed_snapshot("initial_load")
            
            # 步骤3: 增强Cookie处理
            print("\\n🍪 步骤3: Cookie处理")
            self.enhanced_cookie_handler()
            
            # 步骤4: 捕获Cookie处理后状态
            print("\\n📸 步骤4: 捕获Cookie处理后状态")
            self.capture_detailed_snapshot("after_cookie_handling")
            
            # 步骤5: 分析车型数据
            print("\\n🚗 步骤5: 分析车型数据")
            self.analyze_available_models()
            
            # 步骤6: 尝试选择车型并分析导航
            print("\\n🎯 步骤6: 车型选择测试")
            selected_model = self.test_model_selection()
            
            if selected_model:
                # 步骤7: 分析配置流程
                print("\\n⚙️  步骤7: 配置流程分析")
                self.analyze_configuration_steps()
            
            # 步骤8: 生成最终报告
            print("\\n📋 步骤8: 生成分析报告")
            self.generate_final_report()
            
        except Exception as e:
            print(f"❌ 完整流程分析出错: {e}")
        finally:
            print("\\n🏁 分析完成，等待用户确认关闭...")
            input("按 Enter 键关闭浏览器...")
            self.cleanup()
    
    def capture_detailed_snapshot(self, step_name):
        """捕获详细的页面快照"""
        try:
            html_content = self.driver.page_source
            
            # 获取导航状态
            navigation_data = self.extract_navigation_state()
            
            # 获取车型数据
            models_data = self.extract_models_data()
            
            # 获取页面基本信息
            page_info = {
                'url': self.driver.current_url,
                'title': self.driver.title,
                'timestamp': time.time()
            }
            
            snapshot = {
                'html_length': len(html_content),
                'page_info': page_info,
                'navigation': navigation_data,
                'models': models_data
            }
            
            self.html_snapshots[step_name] = snapshot
            
            print(f"    ✅ 已捕获 {step_name} 快照")
            print(f"       HTML长度: {len(html_content):,} 字符")
            print(f"       导航项目: {len(navigation_data)} 个")
            print(f"       车型数量: {len(models_data)} 个")
            
        except Exception as e:
            print(f"    ❌ 捕获快照失败: {e}")
    
    def extract_navigation_state(self):
        """提取导航状态"""
        try:
            nav_container = self.driver.find_element(By.CSS_SELECTOR, 'nav[data-testid="Navigation_Container"]')
            nav_items = nav_container.find_elements(By.CSS_SELECTOR, 'button, a, [role="button"]')
            
            navigation_data = []
            for item in nav_items:
                if item.is_displayed():
                    text = item.text.strip()
                    if text and len(text) < 20:
                        navigation_data.append({
                            'text': text,
                            'enabled': item.is_enabled(),
                            'aria_disabled': item.get_attribute('aria-disabled'),
                            'class': item.get_attribute('class'),
                            'current': 'cwAUaO' in (item.get_attribute('class') or '')
                        })
            
            return navigation_data
        except Exception:
            return []
    
    def extract_models_data(self):
        """提取车型数据"""
        try:
            model_elements = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-cy][class*="ProductTile"]')
            
            models_data = []
            for model in model_elements:
                data_cy = model.get_attribute('data-cy')
                if data_cy and data_cy not in ['header-selling-price', 'sticky-bar', 'disclosure-accordion']:
                    try:
                        text_content = model.text.strip()
                        
                        # 解析价格
                        price = "N/A"
                        if "£" in text_content:
                            import re
                            price_match = re.search(r'£[\d,]+', text_content)
                            if price_match:
                                price = price_match.group()
                        
                        models_data.append({
                            'name': data_cy,
                            'price': price,
                            'text_preview': text_content[:100] + "..." if len(text_content) > 100 else text_content,
                            'class': model.get_attribute('class'),
                            'displayed': model.is_displayed()
                        })
                    except Exception:
                        continue
            
            return models_data
        except Exception:
            return []
    
    def analyze_available_models(self):
        """分析可用车型"""
        current_models = self.extract_models_data()
        
        print(f"    发现 {len(current_models)} 个车型:")
        for i, model in enumerate(current_models, 1):
            print(f"      {i}. {model['name']} - {model['price']}")
        
        self.detected_models = current_models
    
    def test_model_selection(self):
        """测试车型选择"""
        if not self.detected_models:
            print("    ⚠️  没有检测到可用车型")
            return None
        
        # 尝试选择第一个车型
        test_model = self.detected_models[0]
        print(f"    🎯 尝试选择车型: {test_model['name']}")
        
        try:
            model_element = self.driver.find_element(By.CSS_SELECTOR, f'div[data-cy="{test_model["name"]}"]')
            
            # 记录选择前的状态
            before_url = self.driver.current_url
            before_nav = self.extract_navigation_state()
            
            # 点击选择
            self.click_element_safely(model_element)
            
            # 等待页面响应
            time.sleep(3)
            
            # 记录选择后的状态
            after_url = self.driver.current_url
            after_nav = self.extract_navigation_state()
            
            # 分析变化
            url_changed = before_url != after_url
            nav_changed = before_nav != after_nav
            
            if url_changed or nav_changed:
                print(f"    ✅ 车型选择成功!")
                if url_changed:
                    print(f"       URL变化: {before_url} → {after_url}")
                if nav_changed:
                    print(f"       导航状态发生变化")
                
                self.capture_detailed_snapshot("after_model_selection")
                return test_model['name']
            else:
                print(f"    ⚠️  车型点击无明显效果")
                return None
                
        except Exception as e:
            print(f"    ❌ 车型选择失败: {e}")
            return None
    
    def analyze_configuration_steps(self):
        """分析配置步骤"""
        navigation_data = self.extract_navigation_state()
        
        print("    当前导航状态:")
        for nav_item in navigation_data:
            status = "当前" if nav_item['current'] else ("可用" if nav_item['enabled'] and nav_item['aria_disabled'] != 'true' else "不可用")
            print(f"      • {nav_item['text']}: {status}")
        
        # 尝试导航到下一个可用步骤
        available_steps = [nav for nav in navigation_data 
                          if not nav['current'] and nav['enabled'] and nav['aria_disabled'] != 'true']
        
        if available_steps:
            next_step = available_steps[0]
            print(f"    🔄 尝试导航到: {next_step['text']}")
            
            try:
                # 找到对应的导航元素并点击
                nav_element = self.driver.find_element(
                    By.XPATH, 
                    f"//nav[@data-testid='Navigation_Container']//button[text()='{next_step['text']}'] | //nav[@data-testid='Navigation_Container']//a[text()='{next_step['text']}']"
                )
                
                self.click_element_safely(nav_element)
                time.sleep(3)
                
                # 捕获新页面状态
                self.capture_detailed_snapshot(f"step_{next_step['text'].lower()}")
                print(f"    ✅ 成功导航到: {next_step['text']}")
                
            except Exception as e:
                print(f"    ❌ 导航失败: {e}")
    
    def generate_final_report(self):
        """生成最终分析报告"""
        report = {
            'analysis_timestamp': time.time(),
            'snapshots': self.html_snapshots,
            'detected_models': self.detected_models,
            'summary': {
                'total_snapshots': len(self.html_snapshots),
                'total_models_found': len(self.detected_models),
                'html_size_changes': self.calculate_html_changes()
            }
        }
        
        # 保存到文件
        with open("final_configurator_analysis.json", "w", encoding="utf-8") as f:
            json.dump(report, f, indent=2, ensure_ascii=False)
        
        print("    ✅ 最终报告已保存: final_configurator_analysis.json")
        
        # 显示摘要
        print("\\n📊 分析摘要:")
        print(f"    • 捕获快照: {report['summary']['total_snapshots']} 个")
        print(f"    • 检测车型: {report['summary']['total_models_found']} 个")
        for change in report['summary']['html_size_changes']:
            print(f"    • {change}")
    
    def calculate_html_changes(self):
        """计算HTML大小变化"""
        changes = []
        snapshots = list(self.html_snapshots.keys())
        
        for i in range(len(snapshots) - 1):
            current = snapshots[i]
            next_snap = snapshots[i + 1]
            
            current_size = self.html_snapshots[current]['html_length']
            next_size = self.html_snapshots[next_snap]['html_length']
            
            diff = next_size - current_size
            changes.append(f"{current} → {next_snap}: {diff:+,} 字符")
        
        return changes
    
    def cleanup(self):
        """清理资源"""
        if self.driver:
            try:
                self.driver.quit()
                print("🔚 浏览器已关闭")
            except Exception as e:
                print(f"❌ 关闭浏览器出错: {e}")


def main():
    """主函数"""
    url = "https://www.ford.co.uk/shop/build-your-ford/ngc2/ice2/model?catalogId=WAEGB-CGE-2022-FocusMCAGBR202450&series=ACMAA_VS-D3&paint=PN4A7&planId=c"
    
    print("福特配置器最终分析工具")
    print("=" * 80)
    print("🎯 功能特性:")
    print("   • 20秒延迟确保页面完全加载") 
    print("   • 增强的多层Cookie处理机制")
    print("   • 详细的HTML快照和状态对比") 
    print("   • 完整的配置流程分析")
    print("   • 自动车型检测和选择测试")
    print("=" * 80)
    
    analyzer = FinalConfiguratorAnalyzer()
    analyzer.analyze_complete_flow(url)


if __name__ == "__main__":
    main()